home *** CD-ROM | disk | FTP | other *** search
/ PC Format Collection 21 / PC Format CD-ROM Collection 21 (1995-12)(Future Publishing)(GB)[issue 51].iso / resource / numpic.poc < prev    next >
Text File  |  1992-09-11  |  16KB  |  550 lines

  1. /**
  2.  **
  3.  **  NUMPIC.POC  -    Ways to convert a numbered sequence of picture files
  4.  **  to a flic and back.  Also a way to delete the numbered sequence of
  5.  **  pictures when you're done.
  6.  **
  7.  **/
  8.  
  9. #pragma poco library "pdracces.poe"     // extended picture I/O library
  10. #include <errcodes.h>
  11.  
  12. #define NO_DIALOG 0 // Parameter to pdraccess options routine
  13. #define DO_DIALOG 1 // Parameter to pdraccess options routine
  14.  
  15. /*----------------------------------------------------------------------------
  16.  * dialog strings, menu choices, etc...
  17.  *--------------------------------------------------------------------------*/
  18.  
  19. char basename_prompt[]           = "Base name of numbered pictures?";
  20. char delete_basename_prompt[]  = "Base name of numbered files?";
  21. char rgbname_prompt[]           = "Name of (RGB) pic to load?";
  22. char dirfile_prompt[]       = "Choose file of the correct type in directory:";
  23.  
  24. char replace_changes_prompt[]  = "Okay to discard current flic?\n"
  25.                                  "(You have %d unsaved changes)"
  26.                                  ;
  27. char change_flic_size_prompt[] = "Force flic size to picture size?\n\n"
  28.                                  "(Current flic size is %d x %d,\n"
  29.                                  "input picture size is %d x %d.)\n"
  30.                                  ;
  31.  
  32. char menu_prompt[]     = "Convert between Flic and Pictures";
  33. char *menu_choices[] =
  34.     {
  35.     " Save Flic as Pics",
  36.     " Load Pics as Flic",
  37.     " Delete Numbered Files",
  38.     " Load Single (RGB) Pic",
  39.     " Load All in Directory",
  40.     " Exit",
  41.     };
  42.  
  43. enum {MU_EXIT, MU_SAVE, MU_LOAD, MU_DELETE, MU_LOAD1, MU_LOAD_DIR};
  44.  
  45. char load_prompt[]    = "Found %d pictures.\n\n"
  46.                       "The pictures may be appended to the end of the "
  47.                       "current flic, inserted following the current frame, "
  48.                       "or entirely replace the current flic. "
  49.                       "\n\n"
  50.                       "Please select load option:\n"
  51.                       ;
  52. char *load_choices[] = {"Append", "Insert", "Replace", "Cancel"};
  53. enum {LOAD_APPEND=1, LOAD_INSERT, LOAD_REPLACE, LOAD_CANCEL};
  54.  
  55.  
  56. char pdr_prompt[]    = "Please select output format:";
  57. char *pdr_choices[] = {"GIF", "PCX", "TIFF", "Targa", "Macintosh Pict",
  58. "Windows Bitmap",  "Cancel"};
  59. char *pdr_names[]    = {"GIF.PDR", "PCX.PDR", "TIFF.PDR", "TARGA.PDR", 
  60.     "PICT.PDR", "BMP.PDR"};
  61. char *pdr_suffixes[] = {".GIF", ".PCX", ".TIF", ".TGA", ".PCT", ".BMP"};
  62.  
  63. char *start_of_final_digits(char *pt)
  64. /***********************************************************************
  65.  *    returns pointer to the start of the ending number in the string.
  66.  ***********************************************************************/
  67. {
  68.     char c;
  69.     int  len;
  70.     int  i;
  71.  
  72.     i = len = strlen(pt);
  73.     pt += len;
  74.     while (--i >= 0) {
  75.         c = *(--pt);
  76.         if (!(c >= '0' && c <= '9'))
  77.             return(pt+1);
  78.     }
  79.     return pt;
  80. }
  81.  
  82.  
  83. int get_num_name(char *name)
  84. /***********************************************************************
  85.  * Return the number embedded in the "file" portion of a file-name
  86.  * (as opposed to the directory or the suffix.)  Return -1 if none.
  87.  ***********************************************************************/
  88. {
  89.     char *pt;
  90.     char dev[4],dir[70],file[10],suff[5];
  91.  
  92.     fnsplit(name,dev,dir,file,suff);
  93.     if ((pt = start_of_final_digits(file)) == file)
  94.         return(-1);
  95.     return(atoi(pt));
  96. }
  97.  
  98. int count_digits(int num)
  99. /***********************************************************************
  100.  * Return number of digits (base 10) in number.
  101.  ***********************************************************************/
  102. {
  103.     int digits = 1;
  104.  
  105.     while (num > 10) {
  106.         ++digits;
  107.         num /= 10;
  108.     }
  109.     return(digits);
  110. }
  111.  
  112. void make_num_name(char *buf, char *name, int num, int digits)
  113. /***********************************************************************
  114.  * Given a full file name (device, path, file, suffix), a number,
  115.  * and a minimum count of digits,  make a name with the number
  116.  * embedded in the last parts of the 'file' portion of the name.
  117.  * Parameters:
  118.  *        char *buf;        where to put the numbered name
  119.  *        char *name;     the original name.
  120.  *        int  num;        the number.
  121.  *        int  digits;    minimum amount of digits to use.
  122.  * Example:
  123.  *        make_num_name(buf, "c:\pics\sample.gif", 16, 3)
  124.  * leaves "c:\pics\sampl016.gif" in buf.
  125.  ***********************************************************************/
  126. {
  127.     char dev[4],dir[70],file[10],suff[5];
  128.     char nfile[10];
  129.     int  diglen;
  130.     char *pt;
  131.  
  132.     fnsplit(name,dev,dir,file,suff);    // split file into component parts
  133.     if (count_digits(num)>digits)        // if number too big override digits
  134.         digits = count_digits(num);
  135.     pt = start_of_final_digits(file);
  136.     diglen = strlen(pt);        // find out how many digits already in file name
  137.     if (diglen < digits) {        // if less than needed truncate file name
  138.         file[8-digits] = 0;
  139.         diglen = digits;
  140.     } else {                   // Otherwise truncate at first digit
  141.         *pt = 0;
  142.     }
  143.     sprintf(nfile,"%s%0*d", file, diglen, num);
  144.     fnmerge(buf,dev,dir,nfile,suff);
  145. }
  146.  
  147. ErrCode set_up_for_output(char *name)
  148. /***********************************************************************
  149.  * find and load the pdr to handle the output format, get output options.
  150.  * we try to figure out the pdr name from the basename filetype, but
  151.  * if that doesn't work (eg, if there is no suffix on the basename),
  152.  * we prompt the user for the output format using Qmenu.
  153.  * after a pdr is loaded to handle the output, we check whether output
  154.  * options are supported by the pdr, and if so, we call the pdr's
  155.  * options preset dialog.
  156.  **********************************************************************/
  157. {
  158.     ErrCode err;
  159.     int     thechoice;
  160.     char    *pdrname;
  161.     char dev[4],dir[70],file[10],suff[5];
  162.  
  163.     if (Success > (err = PicDriverFindLoad(name))) {
  164.         thechoice = Qmenu(pdr_choices, Array_els(pdr_choices), pdr_prompt);
  165.         if (--thechoice < 0)    // convert choice # to array index,
  166.             return Err_abort;    // if < 0, user picked Cancel or right-clicked
  167.         if (Success > (err = PicDriverLoad(pdr_names[thechoice]))) {
  168.             return Qerror(err, "Cannot load picture driver %s",pdr_names[thechoice]);
  169.         }
  170.         /* If they've picked a driver from list, force suffix to match. */
  171.         fnsplit(name,dev,dir,file,suff);    // split file into component parts
  172.         fnmerge(name,dev,dir,file,pdr_suffixes[thechoice]);
  173.     }
  174.  
  175.     if (PicPdrHasOptions()) {
  176.         if (Success > (err = PicPdrOptionsPreset(DO_DIALOG, 0)))
  177.             return err;
  178.     }
  179.  
  180.     return Success;
  181. }
  182.  
  183. void save_pics(char *name)
  184. /***********************************************************************
  185.  * Save one picture for each frame in current flic.
  186.  ***********************************************************************/
  187. {
  188.     int     i;
  189.     int     count;
  190.     char    nbuf[PATH_SIZE];
  191.     char    suffix[5];
  192.     ErrCode err;
  193.     int     min, max;
  194.  
  195. // Go load the appropriate pdr for outputting the pictures...
  196.  
  197.     if (Success > (err = set_up_for_output(name))) {
  198.         return;
  199.     }
  200.  
  201. // Set up the loop control...
  202.  
  203.     count = GetFrameCount();
  204.  
  205.     if ((min = get_num_name(name)) < 0)
  206.         min = 1;
  207.     max = min + count - 1;
  208.  
  209. // Output the pictures...
  210.  
  211.     for (i = min; i <= max; ++i) {
  212.         make_num_name(nbuf,name,i,count_digits(max));    // make up file name
  213.         printf("Saving %s", nbuf);                      // Put up status line
  214.         if (Success > (err = PicSave(nbuf, NULL))) {
  215.             Qerror(err, "Couldn't save %s", nbuf);
  216.             return;
  217.         }
  218.         NextFrame();
  219.     }
  220.  
  221.     unprintf(); // Get rid of status line
  222. }
  223.  
  224. Boolean fexists(char *name)
  225. /***********************************************************************
  226.  * See whether a file exists.
  227.  ***********************************************************************/
  228. {
  229.     FILE *f;
  230.  
  231.     if ((f = fopen(name, "rb")) != NULL) {
  232.         fclose(f);
  233.         return TRUE;
  234.     }
  235.     else
  236.         return FALSE;
  237. }
  238.  
  239. int count_files(char *base_name)
  240. /***********************************************************************
  241.  * Count up the number of files starting at base_name and
  242.  * numbered sequentially.
  243.  ***********************************************************************/
  244. {
  245.     char nbuf[PATH_SIZE];
  246.     int  count = 0;
  247.     int  base = get_num_name(base_name);
  248.  
  249.     for (;;)
  250.         {
  251.         make_num_name(nbuf, base_name,base+count,0);
  252.         if (!fexists(nbuf))
  253.             break;
  254.         ++count;
  255.         }
  256.     return count;
  257. }
  258.  
  259. Boolean report_about_error(ErrCode err, char *name, int cur_pos, int total)
  260. /***********************************************************************
  261.  * Tell user had error and ask if want to continue.
  262.  ***********************************************************************/
  263. {
  264.     int temp;
  265.  
  266.     Qerror(err, "Can't load %s (%d of %d)", name, cur_pos+1, total);
  267.     temp = total - cur_pos - 1;
  268.     if (temp > 0)
  269.         {
  270.         if (!Qquestion("Continue loading other %d Pics?", temp))
  271.             return FALSE;
  272.         }
  273.     return TRUE;
  274. }
  275.  
  276. void load_pics(char *base_name)
  277. /***********************************************************************
  278.  * Load up a bunch of consecutively numbered files into the flic.
  279.  ***********************************************************************/
  280. {
  281.     int     i;
  282.     int     count;
  283.     int     curframe;
  284.     int     thechoice;
  285.     char    nbuf[PATH_SIZE];
  286.     int     base;
  287.     int     flicw, flich;
  288.     int     picw, pich, picdepth;
  289.     ErrCode err;
  290.     int temp;
  291.  
  292.     base = get_num_name(base_name);
  293.     count = count_files(base_name);
  294.  
  295. // Get the picture size info for the first pic.  This ensures that the
  296. // file exists, and that a pdr can be found by the pdraccess routines to
  297. // process the pictures.
  298.  
  299.     if (Success > (err = PicGetSize(base_name, &picw, &pich, &picdepth))) {
  300.         Qerror(err, "Cannot load %s", base_name);
  301.         return;
  302.     }
  303.  
  304. // Tell the user how many pictures we found to be loaded, and ask for
  305. // the input option (replace/append/insert).  If the replace option is
  306. // choosen, allow the user to change the size of the new flic, if the size
  307. // of the pictures differs from the current flic size.
  308.  
  309.     thechoice = Qchoice(load_choices, Array_els(load_choices), load_prompt, count);
  310.  
  311.     switch (thechoice) {
  312.         case LOAD_REPLACE:
  313.             if (0 != (i = GetChangeCount())) {
  314.                 if (!Qquestion(replace_changes_prompt, i))
  315.                     return;
  316.             }
  317.             GetSize(&flicw, &flich);
  318.             if (flicw != picw || flich != pich) {
  319.                 if (Qquestion(change_flic_size_prompt,flicw,flich,picw,pich)) {
  320.                     flicw = picw;
  321.                     flich = pich;
  322.                 }
  323.             }
  324.             ResizeReset(flicw, flich);
  325.             SetFrameCount(count);
  326.             break;
  327.         case LOAD_APPEND:
  328.             SetFrame(GetFrameCount()-1);    // move to end of flic
  329.             /* fall thru */
  330.         case LOAD_INSERT:
  331.             InsertFrames(count);        // insert enough frames for pics
  332.             NextFrame();                // move to first of inserted frames
  333.             break;
  334.         default:
  335.             return;     // User selected Cancel or right-clicked
  336.     }
  337.  
  338. // If rgb/truecolor data was found in the picture, ask the user for the
  339. // rgb processing option via the pdracces preset dialog.  The choosen
  340. // option will remain in effect throughout the load sequence.
  341.  
  342.     if (picdepth > 8) {
  343.         if (Success > (err = PicRgbOptionsPreset(DO_DIALOG,0)))
  344.             return;
  345.     }
  346.  
  347.     curframe = 1+GetFrame();
  348.  
  349. // Load the pictures...
  350.  
  351.     for (i=0; i < count;) {
  352.         make_num_name(nbuf, base_name, base+i, 0);
  353.         printf("Loading %s into frame %d", nbuf, curframe);
  354.         if (Success > (err = PicLoad(nbuf,NULL))) {
  355.             if (!report_about_error(err, nbuf, i, count))
  356.                 return;
  357.         }
  358.         if (++i < count) {        // don't advance after last picture
  359.             NextFrame();        // (makes multiple insert sequences
  360.             ++curframe;         // easier for the user)
  361.         }
  362.     }
  363.  
  364.     unprintf();         // all done, get rid of top status info line
  365. }
  366.  
  367. void load_pic_list(char **list,  int count)
  368. /***********************************************************************
  369.  * Load a list of files into flic.
  370.  ***********************************************************************/
  371. {
  372.     Boolean got_rgb = FALSE;
  373.     char *name;
  374.     int    picw, pich, picdepth;
  375.     int i;
  376.     ErrCode err;
  377.  
  378.     SetFrameCount(count);
  379.     SetFrame(0);
  380.     for (i=0; i<count; ++i)
  381.     {
  382.         name = *list++;
  383.         /* First check to see if it's RGB */
  384.         if (Success > (err = PicGetSize(name, &picw, &pich, &picdepth))) {
  385.             Qerror(err, "Cannot load %s", name);
  386.             if (!report_about_error(err, name, i, count))
  387.                 return;
  388.         } else {
  389.             /* If RGB (and haven't already) then query how to handle
  390.              * color reduction. */
  391.             if (picdepth > 8 && !got_rgb) {
  392.                 if (Success > (err = PicRgbOptionsPreset(DO_DIALOG,0)))
  393.                     return;
  394.                 got_rgb = TRUE;
  395.             }
  396.             if (Success > (err = PicLoad(name,NULL))) {
  397.                 Qerror(err, "Cannot load %s", name);
  398.                 if (!report_about_error(err, name, i, count))
  399.                     return;
  400.             }
  401.         }
  402.         NextFrame();
  403.     }
  404. }
  405.  
  406. void load_dir(char *base_name)
  407. /***********************************************************************
  408.  * Load a whole directory into flic.
  409.  ***********************************************************************/
  410. {
  411.     char dev[4],dir[70],file[10],suff[5];
  412.     char wild[10];
  413.     char old_dir[80];
  414.     char **file_list;
  415.     int file_count;
  416.  
  417.  
  418.     fnsplit(base_name, dev, dir, file, suff);
  419.     fnmerge(base_name, dev, dir, "", "");
  420.     /* base name is now dir only. */
  421.     GetDir(old_dir);
  422.     SetDir(base_name);
  423.     sprintf(wild, "*%s", suff);
  424.     if ((file_count = DirList(&file_list, wild, FALSE)) > 0)
  425.     {
  426.         load_pic_list(file_list, file_count);
  427.         FreeDirList(&file_list);
  428.     }
  429.     SetDir(old_dir);
  430. }
  431.  
  432. void delete_files(char *base_name)
  433. /***********************************************************************
  434.  * Delete a bunch of consecutively numbered files.
  435.  ***********************************************************************/
  436. {
  437.     char nbuf[PATH_SIZE];
  438.     int  count;
  439.     int  i;
  440.     int  base;
  441.  
  442.     base = get_num_name(base_name);
  443.     count = count_files(base_name);
  444.  
  445. // make extra sure the user wants to do this...
  446.  
  447.     if (!Qquestion("Delete numbered files starting with %s ???", base_name))
  448.         return;
  449.     if (!Qquestion("Are you sure you want to delete all %d"
  450.                    " files starting with:\n      %s?", count, base_name))
  451.         return;
  452.  
  453. // okay, go for it.
  454.  
  455.     for (i=0; i < count; ++i)
  456.         {
  457.         make_num_name(nbuf, base_name, base+i, 0);
  458.         DosDelete(nbuf);
  459.         }
  460. }
  461.  
  462. Boolean do_one_set(char *base_name)
  463. /**********************************************************************
  464.  * Put up main program menu and respond to choices.  Return FALSE if
  465.  * user selects Exit,  TRUE after other commands.
  466.  **********************************************************************/
  467. {
  468.     int choice;
  469.     ErrCode err;
  470.     char *what;
  471.     char *qfile_header = basename_prompt;
  472.  
  473.     choice = Qmenu(menu_choices, Array_els(menu_choices), menu_prompt);
  474.  
  475.     if (choice == MU_LOAD1)        /* It's pretty easy to load one pic. */
  476.         {
  477.         if (Qfile(".TGA;.TIF",  "Load", 
  478.             base_name, base_name, FALSE, rgbname_prompt))
  479.             {
  480.             if (Success > (err = PicLoad(base_name,NULL))) 
  481.                 Qerror(err, "Can't load %s", base_name);
  482.             }
  483.         }
  484.     else
  485.         {
  486.     // Figure out what to put on the file selector action button...
  487.  
  488.         switch (choice)
  489.             {
  490.             case MU_SAVE:
  491.                 what = "Save";
  492.                 break;
  493.             case MU_LOAD:
  494.                 what = "Load";
  495.                 break;
  496.             case MU_DELETE:
  497.                 what = "Delete";
  498.                 qfile_header = delete_basename_prompt;
  499.                 break;
  500.             case MU_LOAD_DIR:
  501.                 what = "Load Dir";
  502.                 qfile_header =  dirfile_prompt;
  503.                 break;
  504.             default:
  505.                 return FALSE;        // User has chosen Exit or right-clicked.
  506.             }
  507.  
  508.     // Ask user for the base file name...
  509.  
  510.         if (!Qfile(".*", what, base_name, base_name, FALSE, qfile_header))
  511.             return TRUE;                // Quit this command, but not program.
  512.  
  513.     // Invoke the requested action...
  514.  
  515.         switch (choice)
  516.             {
  517.             case MU_SAVE:
  518.                 save_pics(base_name);
  519.                 break;
  520.             case MU_LOAD:
  521.                 load_pics(base_name);
  522.                 break;
  523.             case MU_DELETE:
  524.                 delete_files(base_name);
  525.                 break;
  526.             case MU_LOAD_DIR:
  527.                 load_dir(base_name);
  528.                 break;
  529.             }
  530.         }
  531.  
  532.     return TRUE;
  533. }
  534.  
  535.  
  536. void main(void)
  537. /***********************************************************************
  538.  * Call menu routine above until Exit/Cancel.
  539.  **********************************************************************/
  540. {
  541.     static char last_path[PATH_SIZE] = "";
  542.  
  543.     GlobalVarGet("numpic_lastpath",last_path);
  544.  
  545.     while (do_one_set(last_path))
  546.         ;
  547.  
  548.     GlobalVarSet("numpic_lastpath",last_path);
  549. }
  550.